# 作者: 家里蹲 吴越洋
# 2023年03月07日20时01分20秒
from socket import *
import sys
import select

# 新建socket
server_socket=socket(AF_INET,SOCK_STREAM)
# 重用对应地址和端口
server_socket.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
# 绑定socket
server_socket.bind(('',3000))
# 监听
server_socket.listen(10)

# 这里不能accept否则多个客户端接受就会断开
# client_socket,client_addr=server_socket.accept()

epoll=select.epoll()
# 监听标准输入
epoll.register(sys.stdin.fileno(),select.EPOLLIN)
# 监听client_socket
epoll.register(server_socket.fileno(),select.EPOLLIN)
# 客户端字典
client_dict={} # 字典键为文件句柄，值为socket

while True:
    # -1永久等待，轮询注册的事件集合，返回值为[(文件句柄，对应的事件)，(...),....]
    events=epoll.poll(-1)
    for event in events:
        if event[0]==server_socket.fileno():
            client_socket,client_addr=server_socket.accept()
            print(f'{client_addr}连接上了')
            # 加入监听
            epoll.register(client_socket.fileno(),select.EPOLLIN)
            # 加入客户端字典
            client_dict[client_socket.fileno()]=client_socket #client_dict[client_socket.fileno()]==client_socket
        else:
            recv_data=client_dict[event[0]].recv(1024)
            if recv_data:
                # 群发给其他客户端
                for client in client_dict.items():
                    if client[0]!=event[0]:
                        client[1].send(recv_data)
            else:
                # 如果没有从缓冲区读到数据，就是对端断开了
                print('有客户端离线了')
                epoll.unregister(event[0])
                client_dict[event[0]].close()
                del client_dict[event[0]]
                break